package org.example.ding.dto;

import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import org.example.ding.entity.Dish;
import org.example.ding.entity.DishCategory;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 菜品数据传输对象
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DishDto {

    private Long id;

    @NotBlank(message = "菜品名称不能为空")
    @Size(max = 100, message = "菜品名称长度不能超过100个字符")
    private String name;

    @Size(max = 1000, message = "菜品描述长度不能超过1000个字符")
    private String description;

    @NotNull(message = "菜品分类不能为空")
    private Long categoryId;

    private String categoryName;

    // 营养成分 (每100g)
    @NotNull(message = "卡路里不能为空")
    @DecimalMin(value = "0.0", message = "卡路里必须大于等于0")
    @DecimalMax(value = "9999.99", message = "卡路里不能超过9999.99")
    private BigDecimal calories;

    @NotNull(message = "蛋白质含量不能为空")
    @DecimalMin(value = "0.0", message = "蛋白质含量必须大于等于0")
    @DecimalMax(value = "999.99", message = "蛋白质含量不能超过999.99")
    private BigDecimal protein;

    @NotNull(message = "碳水化合物含量不能为空")
    @DecimalMin(value = "0.0", message = "碳水化合物含量必须大于等于0")
    @DecimalMax(value = "999.99", message = "碳水化合物含量不能超过999.99")
    private BigDecimal carbohydrates;

    @NotNull(message = "脂肪含量不能为空")
    @DecimalMin(value = "0.0", message = "脂肪含量必须大于等于0")
    @DecimalMax(value = "999.99", message = "脂肪含量不能超过999.99")
    private BigDecimal fat;

    @DecimalMin(value = "0.0", message = "纤维含量必须大于等于0")
    @DecimalMax(value = "999.99", message = "纤维含量不能超过999.99")
    private BigDecimal fiber;

    @DecimalMin(value = "0.0", message = "钠含量必须大于等于0")
    @DecimalMax(value = "9999.99", message = "钠含量不能超过9999.99")
    private BigDecimal sodium;

    // 菜品属性
    private Dish.SpiceLevel spiceLevel;

    private String tasteProfile;

    private Dish.CookingMethod cookingMethod;

    private String suitableMeals;

    // 统计信息
    private BigDecimal popularityScore;

    private Integer orderCount;

    @Size(max = 255, message = "图片URL长度不能超过255个字符")
    private String imageUrl;

    @DecimalMin(value = "0.0", message = "价格必须大于等于0")
    @DecimalMax(value = "9999.99", message = "价格不能超过9999.99")
    private BigDecimal price;

    private Boolean isAvailable;

    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    /**
     * 从Dish实体创建DTO
     */
    public static DishDto fromDish(Dish dish) {
        DishDto dto = new DishDto();
        dto.setId(dish.getId());
        dto.setName(dish.getName());
        dto.setDescription(dish.getDescription());
        
        if (dish.getCategory() != null) {
            dto.setCategoryId(dish.getCategory().getId());
            dto.setCategoryName(dish.getCategory().getName());
        }
        
        dto.setCalories(dish.getCalories());
        dto.setProtein(dish.getProtein());
        dto.setCarbohydrates(dish.getCarbohydrates());
        dto.setFat(dish.getFat());
        dto.setFiber(dish.getFiber());
        dto.setSodium(dish.getSodium());
        
        dto.setSpiceLevel(dish.getSpiceLevel());
        dto.setTasteProfile(dish.getTasteProfile());
        dto.setCookingMethod(dish.getCookingMethod());
        dto.setSuitableMeals(dish.getSuitableMeals());
        
        dto.setPopularityScore(dish.getPopularityScore());
        dto.setOrderCount(dish.getOrderCount());
        dto.setImageUrl(dish.getImageUrl());
        dto.setPrice(dish.getPrice());
        dto.setIsAvailable(dish.getIsAvailable());
        
        dto.setCreatedAt(dish.getCreatedAt());
        dto.setUpdatedAt(dish.getUpdatedAt());
        
        return dto;
    }

    /**
     * 转换为Dish实体
     */
    public Dish toDish() {
        Dish dish = new Dish();
        dish.setId(this.id);
        dish.setName(this.name);
        dish.setDescription(this.description);
        
        dish.setCalories(this.calories);
        dish.setProtein(this.protein);
        dish.setCarbohydrates(this.carbohydrates);
        dish.setFat(this.fat);
        dish.setFiber(this.fiber != null ? this.fiber : BigDecimal.ZERO);
        dish.setSodium(this.sodium != null ? this.sodium : BigDecimal.ZERO);
        
        dish.setSpiceLevel(this.spiceLevel != null ? this.spiceLevel : Dish.SpiceLevel.NONE);
        dish.setTasteProfile(this.tasteProfile);
        dish.setCookingMethod(this.cookingMethod);
        dish.setSuitableMeals(this.suitableMeals);
        
        dish.setImageUrl(this.imageUrl);
        dish.setPrice(this.price);
        dish.setIsAvailable(this.isAvailable != null ? this.isAvailable : true);
        
        return dish;
    }

    /**
     * 更新Dish实体
     */
    public void updateDish(Dish dish) {
        if (name != null) dish.setName(name);
        if (description != null) dish.setDescription(description);
        
        if (calories != null) dish.setCalories(calories);
        if (protein != null) dish.setProtein(protein);
        if (carbohydrates != null) dish.setCarbohydrates(carbohydrates);
        if (fat != null) dish.setFat(fat);
        if (fiber != null) dish.setFiber(fiber);
        if (sodium != null) dish.setSodium(sodium);
        
        if (spiceLevel != null) dish.setSpiceLevel(spiceLevel);
        if (tasteProfile != null) dish.setTasteProfile(tasteProfile);
        if (cookingMethod != null) dish.setCookingMethod(cookingMethod);
        if (suitableMeals != null) dish.setSuitableMeals(suitableMeals);
        
        if (imageUrl != null) dish.setImageUrl(imageUrl);
        if (price != null) dish.setPrice(price);
        if (isAvailable != null) dish.setIsAvailable(isAvailable);
    }

    /**
     * 获取辣度描述
     */
    public String getSpiceLevelDescription() {
        return spiceLevel != null ? spiceLevel.getDescription() : "不辣";
    }

    /**
     * 获取烹饪方式描述
     */
    public String getCookingMethodDescription() {
        return cookingMethod != null ? cookingMethod.getDescription() : "未知";
    }

    /**
     * 计算营养密度 (蛋白质/卡路里)
     */
    public BigDecimal getProteinDensity() {
        if (calories == null || calories.compareTo(BigDecimal.ZERO) == 0 || protein == null) {
            return BigDecimal.ZERO;
        }
        return protein.divide(calories, 4, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 获取营养评分 (简单算法)
     */
    public String getNutritionGrade() {
        if (calories == null || protein == null) {
            return "未评级";
        }
        
        BigDecimal proteinDensity = getProteinDensity();
        double caloriesValue = calories.doubleValue();
        
        // 简单的营养评分算法
        if (proteinDensity.doubleValue() > 0.15 && caloriesValue < 200) {
            return "A";
        } else if (proteinDensity.doubleValue() > 0.10 && caloriesValue < 300) {
            return "B";
        } else if (proteinDensity.doubleValue() > 0.05 && caloriesValue < 500) {
            return "C";
        } else {
            return "D";
        }
    }

    /**
     * 判断是否为高蛋白菜品
     */
    public boolean isHighProtein() {
        return protein != null && protein.compareTo(new BigDecimal("20")) >= 0;
    }

    /**
     * 判断是否为低卡路里菜品
     */
    public boolean isLowCalorie() {
        return calories != null && calories.compareTo(new BigDecimal("200")) <= 0;
    }
}
